package com.insight.repository;

import com.insight.entity.MetadataIndex;
import com.insight.entity.MetadataTable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * T050: MetadataIndex Repository接口
 * 索引元数据数据访问层,使用Spring Data JPA
 *
 * @author Insight Team
 */
@Repository
public interface MetadataIndexRepository extends JpaRepository<MetadataIndex, Long> {

    /**
     * 根据表查找所有索引元数据
     *
     * @param table 表
     * @return 索引元数据列表
     */
    List<MetadataIndex> findByTable(MetadataTable table);

    /**
     * 根据表ID查找所有索引元数据
     *
     * @param tableId 表ID
     * @return 索引元数据列表
     */
    @Query("SELECT mi FROM MetadataIndex mi WHERE mi.table.id = :tableId")
    List<MetadataIndex> findByTableId(@Param("tableId") Long tableId);

    /**
     * 根据表和索引名查找索引元数据
     *
     * @param table     表
     * @param indexName 索引名
     * @return 索引元数据Optional
     */
    Optional<MetadataIndex> findByTableAndIndexName(MetadataTable table, String indexName);

    /**
     * 根据表ID和索引名查找索引元数据
     *
     * @param tableId   表ID
     * @param indexName 索引名
     * @return 索引元数据Optional
     */
    @Query("SELECT mi FROM MetadataIndex mi WHERE mi.table.id = :tableId AND mi.indexName = :indexName")
    Optional<MetadataIndex> findByTableIdAndIndexName(@Param("tableId") Long tableId, @Param("indexName") String indexName);

    /**
     * 根据索引类型查找索引元数据
     *
     * @param indexType 索引类型
     * @return 索引元数据列表
     */
    List<MetadataIndex> findByIndexType(String indexType);

    /**
     * 根据表和索引类型查找索引元数据
     *
     * @param table     表
     * @param indexType 索引类型
     * @return 索引元数据列表
     */
    List<MetadataIndex> findByTableAndIndexType(MetadataTable table, String indexType);

    /**
     * 查找表中的唯一索引
     *
     * @param table 表
     * @return 唯一索引元数据列表
     */
    List<MetadataIndex> findByTableAndIsUniqueTrue(MetadataTable table);

    /**
     * 查找表中的非唯一索引
     *
     * @param table 表
     * @return 非唯一索引元数据列表
     */
    List<MetadataIndex> findByTableAndIsUniqueFalse(MetadataTable table);

    /**
     * 根据列名模糊查找索引
     * 查找包含指定列的索引
     *
     * @param columnName 列名
     * @return 索引元数据列表
     */
    @Query("SELECT mi FROM MetadataIndex mi WHERE mi.columnNames LIKE %:columnName%")
    List<MetadataIndex> findByColumnNamesContaining(@Param("columnName") String columnName);

    /**
     * 根据表和列名模糊查找索引
     *
     * @param table      表
     * @param columnName 列名
     * @return 索引元数据列表
     */
    @Query("SELECT mi FROM MetadataIndex mi WHERE mi.table = :table AND mi.columnNames LIKE %:columnName%")
    List<MetadataIndex> findByTableAndColumnNamesContaining(@Param("table") MetadataTable table, @Param("columnName") String columnName);

    /**
     * 分页查询指定表的索引元数据
     *
     * @param table    表
     * @param pageable 分页参数
     * @return 索引元数据分页结果
     */
    Page<MetadataIndex> findByTable(MetadataTable table, Pageable pageable);

    /**
     * 分页查询指定表ID的索引元数据
     *
     * @param tableId  表ID
     * @param pageable 分页参数
     * @return 索引元数据分页结果
     */
    @Query("SELECT mi FROM MetadataIndex mi WHERE mi.table.id = :tableId")
    Page<MetadataIndex> findByTableId(@Param("tableId") Long tableId, Pageable pageable);

    /**
     * 查找指定时间范围内更新的索引元数据
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 索引元数据列表
     */
    List<MetadataIndex> findByUpdatedAtBetween(LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 查找指定表在时间范围内更新的索引元数据
     *
     * @param table     表
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 索引元数据列表
     */
    List<MetadataIndex> findByTableAndUpdatedAtBetween(MetadataTable table, LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 统计指定表的索引数量
     *
     * @param table 表
     * @return 索引数量
     */
    long countByTable(MetadataTable table);

    /**
     * 统计指定表ID的索引数量
     *
     * @param tableId 表ID
     * @return 索引数量
     */
    @Query("SELECT COUNT(mi) FROM MetadataIndex mi WHERE mi.table.id = :tableId")
    long countByTableId(@Param("tableId") Long tableId);

    /**
     * 统计指定表的唯一索引数量
     *
     * @param table 表
     * @return 唯一索引数量
     */
    long countByTableAndIsUniqueTrue(MetadataTable table);

    /**
     * 检查索引是否存在
     *
     * @param table     表
     * @param indexName 索引名
     * @return 是否存在
     */
    boolean existsByTableAndIndexName(MetadataTable table, String indexName);

    /**
     * 删除指定表的所有索引元数据
     *
     * @param table 表
     */
    void deleteByTable(MetadataTable table);

    /**
     * 删除指定表ID的所有索引元数据
     *
     * @param tableId 表ID
     */
    @Modifying
    @Transactional
    @Query("DELETE FROM MetadataIndex mi WHERE mi.table.id = :tableId")
    void deleteByTableId(@Param("tableId") Long tableId);

    /**
     * 批量保存索引元数据
     * 重写saveAll方法以优化批量插入性能
     *
     * @param indexes 索引元数据列表
     * @return 保存后的索引元数据列表
     */
    @Override
    <S extends MetadataIndex> List<S> saveAll(Iterable<S> indexes);
}
